package org.uim.cricket.analyzer.report;

import java.util.Calendar;

import org.apache.commons.lang3.StringEscapeUtils;
import org.uim.cricket.entities.Official;
import org.uim.cricket.entities.Player;
import org.uim.cricket.entities.match.CricketMatch;
import org.uim.cricket.entities.match.Ground;
import org.uim.cricket.entities.match.MatchResult;
import org.uim.cricket.entities.match.ResultType;
import org.uim.cricket.entities.match.SeriesPlayed;

public class XMLMatchHeaderReporting {
	
	private StringBuilder xml = new StringBuilder();
	
	public StringBuilder getMatchHeaderXMLText(CricketMatch match) throws Exception {
		xml.append("<CricketMatch");
        xml.append(appendXMLAttrib("type", match.getId().getPrefix(), false));
        xml.append(appendXMLAttrib("id", match.getId().getInternationalID(), false));
        if (match.getSpans() != null) {
            xml.append(appendXMLAttrib("spanType", match.getSpans().getSpanType().toString(), false));
            xml.append(appendXMLAttrib("spans", match.getSpans().getSpans(), false));
        }
        xml.append(">\n");
        
        this.appendXMLLineIndent(xml, 1);
        xml.append("<Teams");
        xml.append(this.appendXMLAttrib("team1", match.getTeam1(), true));
        xml.append(this.appendXMLAttrib("team2", match.getTeam2(), true));
        xml.append(" />\n");
        
        this.appendGround(match, 1);
        this.appendSeries(match, 1);
        this.appendResult(match, 1);
        this.appendDates(match, 1);
        
        this.appendXMLLineIndent(xml, 1);
        xml.append("<Notes>\n");
        
        if (match.getToss() != null) {
            this.appendXMLLineIndent(xml, 2);
            xml.append("<Toss");
            xml.append(this.appendXMLAttrib("won", match.getToss().getTossWon(), true));
            xml.append(this.appendXMLAttrib("fielded", match.getToss().isFielded(), false));
            xml.append(" />\n");
        }
        if (match.getManOfTheMatch() != null) {
            this.appendXMLLineIndent(xml, 2);
            xml.append("<ManOfTheMatch>\n");
            Player[] moms = match.getManOfTheMatch();
            
            for (int i=0;i<moms.length;i++) {
                this.appendXMLLineIndent(xml, 3);
                xml.append("<Player");
                xml.append(this.appendXMLAttrib("name", moms[i].getTitleName(), true));
                xml.append(this.appendXMLAttrib("team", moms[i].getCountry(), true));
                xml.append(" />\n");
            }
            this.appendXMLLineIndent(xml, 2);
            xml.append("</ManOfTheMatch>\n");
        }
        if (match.getManOfTheSeries() != null) {
            this.appendXMLLineIndent(xml, 2);
            xml.append("<ManOfTheSeries>\n");
            Player[] moms = match.getManOfTheSeries();
            
            for (int i=0;i<moms.length;i++) {
                this.appendXMLLineIndent(xml, 3);
                xml.append("<Player");
                xml.append(this.appendXMLAttrib("name", moms[i].getTitleName(), true));
                xml.append(this.appendXMLAttrib("team", moms[i].getCountry(), true));
                xml.append(" />\n");
            }
            this.appendXMLLineIndent(xml, 2);
            xml.append("</ManOfTheSeries>\n");
        }
        if (match.getOfficials() != null) {
            this.appendXMLLineIndent(xml, 2);
            xml.append("<Officials>\n");
            if (match.getOfficials().getUmpires() != null) {
                Official[] offs = match.getOfficials().getUmpires();
                
                for (int i=0;i<offs.length;i++) {
                    this.appendXMLLineIndent(xml, 3);
                    xml.append("<Umpire");
                    if (offs[i].getId() != null) {
                        xml.append(this.appendXMLAttrib("id", offs[i].getId(), false));
                    }
                    if (offs[i].getTitleName() != null) {
                        xml.append(this.appendXMLAttrib("name", offs[i].getTitleName(), true));
                    }
                    if (offs[i].getCountry() != null) {
                        xml.append(this.appendXMLAttrib("country", offs[i].getCountry(), true));
                    }
                    if (offs[i].getShortName() != null) {
                        xml.append(this.appendXMLAttrib("shortname", offs[i].getShortName(), true));
                    }
                    xml.append(" />\n");
                }
                
            }
            if (match.getOfficials().getTvUmpire() != null) {
                this.appendXMLLineIndent(xml, 3);
                xml.append("<TVUmpire");
                if (match.getOfficials().getTvUmpire().getId() != null) {
                    xml.append(this.appendXMLAttrib("id", match.getOfficials().getTvUmpire().getId(), false));
                }
                if (match.getOfficials().getTvUmpire().getTitleName() != null) {
                    xml.append(this.appendXMLAttrib("name", match.getOfficials().getTvUmpire().getTitleName(), true));
                }
                if (match.getOfficials().getTvUmpire().getCountry() != null) {
                    xml.append(this.appendXMLAttrib("country", match.getOfficials().getTvUmpire().getCountry(), true));
                }
                if (match.getOfficials().getTvUmpire().getShortName() != null) {
                    xml.append(this.appendXMLAttrib("shortname", match.getOfficials().getTvUmpire().getShortName(), true));
                }
                xml.append(" />\n");
            }
            if (match.getOfficials().getReservedUmpire() != null) {
                this.appendXMLLineIndent(xml, 3);
                xml.append("<ReservedUmpire");
                if (match.getOfficials().getReservedUmpire().getId() != null) {
                    xml.append(this.appendXMLAttrib("id", match.getOfficials().getReservedUmpire().getId(), false));
                }
                if (match.getOfficials().getReservedUmpire().getTitleName() != null) {
                    xml.append(this.appendXMLAttrib("name", match.getOfficials().getReservedUmpire().getTitleName(), true));
                }
                if (match.getOfficials().getReservedUmpire().getCountry() != null) {
                    xml.append(this.appendXMLAttrib("country", match.getOfficials().getReservedUmpire().getCountry(), true));
                }
                if (match.getOfficials().getReservedUmpire().getShortName() != null) {
                    xml.append(this.appendXMLAttrib("shortname", match.getOfficials().getReservedUmpire().getShortName(), true));
                }
                xml.append(" />\n");
            }
            if (match.getOfficials().getReferee() != null) {
                this.appendXMLLineIndent(xml, 3);
                xml.append("<Referee");
                if (match.getOfficials().getReferee().getId() != null) {
                    xml.append(this.appendXMLAttrib("id", match.getOfficials().getReferee().getId(), false));
                }
                if (match.getOfficials().getReferee().getTitleName() != null) {
                    xml.append(this.appendXMLAttrib("name", match.getOfficials().getReferee().getTitleName(), true));
                }
                if (match.getOfficials().getReferee().getCountry() != null) {
                    xml.append(this.appendXMLAttrib("country", match.getOfficials().getReferee().getCountry(), true));
                }
                if (match.getOfficials().getReferee().getShortName() != null) {
                    xml.append(this.appendXMLAttrib("shortname", match.getOfficials().getReferee().getShortName(), true));
                }
                xml.append(" />\n");
            }
            this.appendXMLLineIndent(xml, 2);
            xml.append("</Officials>\n");
        }
        if (match.getDebutPlayers() != null) {
            this.appendXMLLineIndent(xml, 2);
            xml.append("<Debuts>\n");
            Player[] moms = match.getDebutPlayers();
            
            for (int i=0;i<moms.length;i++) {
                this.appendXMLLineIndent(xml, 3);
                xml.append("<Player");
                if (moms[i].getTitleName() != null) {
                    xml.append(this.appendXMLAttrib("name", moms[i].getTitleName(), true));
                }
                if (moms[i].getCountry() != null) {
                    xml.append(this.appendXMLAttrib("team", moms[i].getCountry(), true));
                }
                xml.append(" />\n");
            }
            this.appendXMLLineIndent(xml, 2);
            xml.append("</Debuts>\n");
        }
        this.appendXMLLineIndent(xml, 1);
        xml.append("</Notes>\n");
        
        return xml;
	}
	
	private void appendDates(CricketMatch match, int indent) {
        if (match.getDates() == null) return;
        Calendar[] dates = match.getDates().getDates();
        if (dates == null) return;
        
        this.appendXMLLineIndent(xml, indent);
        
        xml.append("<Dates>\n");
        for (int i=0;i < dates.length;i++) {
        	if (dates[i]==null) continue;
            this.appendXMLLineIndent(xml, indent + 1);
            xml.append("<Date>").append(dates[i].get(Calendar.DATE)).append('/');
            xml.append(dates[i].get(Calendar.MONTH)+1).append('/');
            xml.append(dates[i].get(Calendar.YEAR)).append("</Date>\n");
        }
        this.appendXMLLineIndent(xml, indent);
        xml.append("</Dates>\n");
    }
	
	private void appendResult(CricketMatch match, int indent) {
        this.appendXMLLineIndent(xml, indent);
        
        MatchResult r = match.getResult();
        xml.append("<Result");
        if (r.getResultType() == null) r.setResultType(ResultType.ABONDANT);
        xml.append(this.appendXMLAttrib("id", r.getResultType().toString(), false));
        if (r.getWonTeam() != null) {
            xml.append(this.appendXMLAttrib("winteam", r.getWonTeam(), true));
        }
        if (r.getWonType() != null) {
            xml.append(this.appendXMLAttrib("wintype", r.getWonType().toString(), false));
        }
        if (r.getMargin() >= 0) {
            xml.append(this.appendXMLAttrib("margin", r.getMargin() + "", false));
        }
        if (r.getRemainingBalls() >= 0) {
            xml.append(this.appendXMLAttrib("remainingBalls", r.getRemainingBalls() + "", false));
        }
        if (r.isByDuckworthLewis()) {
            xml.append(this.appendXMLAttrib("dl", r.isByDuckworthLewis(), false));
        }
        xml.append(" />\n");
    }
	
	private void appendGround(CricketMatch match, int indent) {
        this.appendXMLLineIndent(xml, indent);
        
        Ground g = match.getGround();
        xml.append("<Ground");
        xml.append(this.appendXMLAttrib("id", g.getId(), false));
        xml.append(this.appendXMLAttrib("name", g.getName().trim(), true));
        xml.append(this.appendXMLAttrib("daynight", match.isDayNight(), false));
        if (g.getGroundLink() != null) {
        	xml.append(this.appendXMLAttrib("link", g.getGroundLink(), false));
        }
        if (match.getVenue() != null) {
            xml.append(this.appendXMLAttrib("venue", match.getVenue().toString(), false));
        }
        xml.append(" />\n");
    }
	
	private void appendSeries(CricketMatch match, int indent) {
        this.appendXMLLineIndent(xml, indent);
        
        SeriesPlayed s = match.getSeries();
        xml.append("<Series");
        xml.append(appendXMLAttrib("id", s.getId(), false));
        xml.append(appendXMLAttrib("name", s.getName(), true));
        xml.append(appendXMLAttrib("match", s.getMatch(), true));
        xml.append(appendXMLAttrib("season", s.getSeason(), true));
        if (s.getSeriesLink() != null) {
        	xml.append(appendXMLAttrib("link", s.getSeriesLink(), false));
        }
        xml.append(">\n");
        appendXMLLineIndent(xml, indent + 1);
        if (s.getResultAfterThisMatch() != null) {
            xml.append(StringEscapeUtils.escapeXml(s.getResultAfterThisMatch()));
            xml.append("\n");
        }
        this.appendXMLLineIndent(xml, indent);
        xml.append("</Series>\n");
    }
    
	private String appendXMLAttrib(String attrb, boolean value, boolean doencode) {
        return this.appendXMLAttrib(attrb, (value ? "true" : "false"), doencode);
    }
    private String appendXMLAttrib(String attrb, int value, boolean doencode) {
        return this.appendXMLAttrib(attrb, value + "", doencode);
    }
    private String appendXMLAttrib(String attrb, String value, boolean doencode) {
        if (doencode) {
            return " " + attrb + "=\"" + StringEscapeUtils.escapeXml(value) + "\"";
        } else {
            return " " + attrb + "=\"" + (value) + "\"";
        }
    }
    private void appendXMLLineIndent(StringBuilder xml, int indent) {
        for (int i=0;i<indent;i++) {
            xml.append('\t');
        }
    }
}
